﻿#include "FITKNastranAdaptorModel.h"
#include "FITKNastranBDFIOTool.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"

#include "FITK_Kernel/FITKCore/FITKVec3D.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMeshPartVTK.h"

#include <QSet>

namespace Nastran
{
    bool FITKNastranAdaptorModelNode::adaptR()
    {
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !_reader) return false;
        //后退一行
        _reader->backLine();
        //获取读取工具和网格数据
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh || !readTool) return false;
        QStringList data = readTool->readNastranBDFLineSpliter();
        if (data.isEmpty() || !data.at(0).toUpper().startsWith("GRID")) return false;
        //获取点的数据
        double coor[3] = { 0,0,0 };
        if (data.size() < 6) return false;
        bool ok = false;
        int id = data.at(1).trimmed().toInt(&ok);
        if (!ok) return false;
        for (int i = 0; i < 3; ++i)
        {
            coor[i] = readTool->stringToDouble(data.at(3 + i), ok);
            if (!ok) return false;
        }
        mesh->addNode(id, coor[0], coor[1], coor[2]);
        return true;
    }

    bool FITKNastranAdaptorModelNode::adaptW()
    {
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !_writer) return false;
        //获取写出工具和网格数据
        FITKNastranBDFIOWriterTool* writeTool = _writer->getWriterTool();
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh || !writeTool) return false;
        int count = mesh->getNodeCount();
        for (int i = 0; i < count; ++i)
        {
            Core::FITKNode* node = mesh->getNodeAt(i);
            if (!node) continue;
            bool ok = false;
            int id = node->getNodeID();
            double coor[3] = { 0,0,0 };
            node->getCoor(coor);
            //获取数据
            QStringList data;
            data.append("GRID");
            data.append(QString::number(id));
            data.append("");
            data.append(writeTool->doubleToString(coor[0], ok));
            data.append(writeTool->doubleToString(coor[1], ok));
            data.append(writeTool->doubleToString(coor[2], ok));
            //写出数据
            writeTool->writeData(data);
        }
        return true;
    }

    bool FITKNastranAdaptorModelElement::adaptR()
    {
        if (!_reader || !_dataObj) return false;
        //后退一行
        _reader->backLine();
        //获取读取工具和网格数据
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        if (!readTool) return false;
        //获取数据
        QStringList data = readTool->readNastranBDFLineSpliter();
        if (data.isEmpty()) return false;
        QString elementType = data.at(0).toUpper();
        //读入单元
        bool readOK = false;
        if (elementType.startsWith("CTRIA3"))
            readOK = this->readCTRIA3(data);
        else if (elementType.startsWith("CQUAD4"))
            readOK = this->readCQUAD4(data);
        else if (elementType.startsWith("CHEXA"))
            readOK = this->readCHEXA(data);
        else if (elementType.startsWith("CTETRA"))
            readOK = this->readCTETRA(data);
        else if (elementType.startsWith("CBAR"))
            readOK = this->readCBAR(data);
        return readOK;
    }

    bool FITKNastranAdaptorModelElement::adaptW()
    {
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !_writer) return false;
        //获取网格数据
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh) return false;
        //获取全部的单元ID
        int count = mesh->getElementCount();
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKAbstractElement* element = mesh->getElementAt(i);
            if (!element)continue;
            Interface::FITKModelEnum::FITKEleType eType = element->getEleType();
            if (eType == Interface::FITKModelEnum::FITKEleType::Line2)
                this->writeCBAR(element);
            else if (eType == Interface::FITKModelEnum::FITKEleType::Tri3)
                this->writeCTRIA3(element);
            else if (eType == Interface::FITKModelEnum::FITKEleType::Quad4)
                this->writeCQUAD4(element);
            else if (eType == Interface::FITKModelEnum::FITKEleType::Hex8 || eType == Interface::FITKModelEnum::FITKEleType::Hex20)
                this->writeCHEXA(element);
            else if (eType == Interface::FITKModelEnum::FITKEleType::Tet4 || eType == Interface::FITKModelEnum::FITKEleType::Tet10)
                this->writeCTETRA(element);
        }
        return true;
    }

    bool FITKNastranAdaptorModelElement::readCBAR(QStringList data)
    {
        if (data.size() < 5)return false;
        //网格数据和读取工具
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !readTool) return false;
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh) return false;
        //获取单元的数据
        bool ok = false;
        int elementID = data.at(1).trimmed().toInt(&ok);
        if (!ok) return false;
        int pID = data.at(2).trimmed().toInt(&ok);//物理属性ID
        if (!ok) return false;
        Interface::FITKAbaMeshPartVTK::AbaEleType elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::B31;
        int nodeNum = 2;//节点数量
        QList<int> nodeIDs;//节点编号链表
        for (int i = 0; i < nodeNum; ++i)
        {
            int nodeID = data.at(i + 3).trimmed().toInt(&ok);
            if (!ok) return false;
            nodeIDs.append(nodeID);
        }
        mesh->appendElement(elementType, elementID, nodeIDs);
        readTool->insertElementProp(pID, elementID);
        return true;
    }

    bool FITKNastranAdaptorModelElement::readCTRIA3(QStringList data)
    {
        if (data.size() < 6)return false;
        //网格数据和读取工具
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !readTool) return false;
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh) return false;
        //获取单元的数据
        bool ok = false;
        int elementID = data.at(1).trimmed().toInt(&ok);
        if (!ok) return false;
        int pID = data.at(2).trimmed().toInt(&ok);//物理属性ID
        if (!ok) return false;
        Interface::FITKAbaMeshPartVTK::AbaEleType elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::S3;
        int nodeNum = 3;//节点数量
        QList<int> nodeIDs;//节点编号链表
        for (int i = 0; i < nodeNum; ++i)
        {
            int nodeID = data.at(i + 3).trimmed().toInt(&ok);
            if (!ok) return false;
            nodeIDs.append(nodeID);
        }
        mesh->appendElement(elementType, elementID, nodeIDs);
        readTool->insertElementProp(pID, elementID);
        return true;
    }

    bool FITKNastranAdaptorModelElement::readCQUAD4(QStringList data)
    {
        if (data.size() < 7)return false;
        //网格数据和读取工具
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !readTool) return false;
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh) return false;
        //获取单元的数据
        bool ok = false;
        int elementID = data.at(1).trimmed().toInt(&ok);
        if (!ok) return false;
        int pID = data.at(2).trimmed().toInt(&ok);//物理属性ID
        if (!ok) return false;
        Interface::FITKAbaMeshPartVTK::AbaEleType elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::S4;
        int nodeNum = 4;//节点数量
        QList<int> nodeIDs;//节点编号链表
        for (int i = 0; i < nodeNum; ++i)
        {
            int nodeID = data.at(i + 3).trimmed().toInt(&ok);
            if (!ok) return false;
            nodeIDs.append(nodeID);
        }
        mesh->appendElement(elementType, elementID, nodeIDs);
        readTool->insertElementProp(pID, elementID);
        return true;
    }

    bool FITKNastranAdaptorModelElement::readCHEXA(QStringList data)
    {
        if (data.size() < 11)return false;
        //网格数据和读取工具
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !readTool) return false;
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh) return false;
        //获取单元的数据
        bool ok = false;
        int elementID = data.at(1).trimmed().toInt(&ok);
        if (!ok) return false;
        int pID = data.at(2).trimmed().toInt(&ok);//物理属性ID
        if (!ok) return false;
        int nodeNum = 8;//节点数量
        QList<int> nodeIDs;//节点编号链表
        Interface::FITKAbaMeshPartVTK::AbaEleType elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::C3D8;
        if (data.size() > 11 && !data.at(11).trimmed().isEmpty())
        {
            nodeNum = 20;
            elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::C3D20;
            if (data.size() < 23) return false;
        }
        for (int i = 0; i < nodeNum; ++i)
        {
            int nodeID = data.at(i + 3).trimmed().toInt(&ok);
            if (!ok) return false;
            nodeIDs.append(nodeID);
        }
        mesh->appendElement(elementType, elementID, nodeIDs);
        readTool->insertElementProp(pID, elementID);
        return true;
    }

    bool FITKNastranAdaptorModelElement::readCTETRA(QStringList data)
    {
        if (data.size() < 7)return false;
        //网格数据和读取工具
        FITKNastranBDFIOReaderTool* readTool = _reader->getReaderTool();
        AbaqusData::FITKAbaqusPart *partData = dynamic_cast<AbaqusData::FITKAbaqusPart *>(_dataObj);
        if (!partData || !readTool) return false;
        Interface::FITKAbaMeshPartVTK* mesh = partData->getMesh();
        if (!mesh) return false;
        //获取单元的数据
        bool ok = false;
        int elementID = data.at(1).trimmed().toInt(&ok);
        if (!ok) return false;
        int pID = data.at(2).trimmed().toInt(&ok);//物理属性ID
        if (!ok) return false;
        int nodeNum = 4;//节点数量
        QList<int> nodeIDs;//节点编号链表
        Interface::FITKAbaMeshPartVTK::AbaEleType elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::C3D4;
        if (data.size() > 7 && !data.at(7).trimmed().isEmpty())
        {
            nodeNum = 10;
            elementType = Interface::FITKAbaMeshPartVTK::AbaEleType::C3D10;
            if (data.size() < 13) return false;
        }
        for (int i = 0; i < nodeNum; ++i)
        {
            int nodeID = data.at(i + 3).trimmed().toInt(&ok);
            if (!ok) return false;
            nodeIDs.append(nodeID);
        }
        mesh->appendElement(elementType, elementID, nodeIDs);
        readTool->insertElementProp(pID, elementID);
        return true;
    }

    bool FITKNastranAdaptorModelElement::writeCBAR(Interface::FITKAbstractElement * element)
    {
        if (!element || !_writer) return false;
        //获取写出工具
        FITKNastranBDFIOWriterTool* writeTool = _writer->getWriterTool();
        if (!writeTool) return false;
        int eID = element->getEleID();
        //获取数据
        QStringList data;
        data.append("CBAR");
        data.append(QString::number(eID));
        data.append(QString::number(writeTool->getPropIDByEID(eID)));
        QList<int> nodeIDs = element->getAllNodes();
        for (QList<int>::iterator iter = nodeIDs.begin(); iter != nodeIDs.end(); ++iter)
            data.append(QString::number(*iter));
        //写出数据
        writeTool->writeData(data);
        return true;
    }

    bool FITKNastranAdaptorModelElement::writeCTRIA3(Interface::FITKAbstractElement* element)
    {
        if (!element || !_writer) return false;
        //获取写出工具
        FITKNastranBDFIOWriterTool* writeTool = _writer->getWriterTool();
        if (!writeTool) return false;
        int eID = element->getEleID();
        //获取数据
        QStringList data;
        data.append("CTRIA3");
        data.append(QString::number(eID));
        data.append(QString::number(writeTool->getPropIDByEID(eID)));
        QList<int> nodeIDs = element->getAllNodes();
        for (QList<int>::iterator iter = nodeIDs.begin(); iter != nodeIDs.end(); ++iter)
            data.append(QString::number(*iter));
        //写出数据
        writeTool->writeData(data);
        return true;
    }

    bool FITKNastranAdaptorModelElement::writeCQUAD4(Interface::FITKAbstractElement* element)
    {
        if (!element || !_writer) return false;
        //获取写出工具
        FITKNastranBDFIOWriterTool* writeTool = _writer->getWriterTool();
        if (!writeTool) return false;
        int eID = element->getEleID();
        //获取数据
        QStringList data;
        data.append("CQUAD4");
        data.append(QString::number(eID));
        data.append(QString::number(writeTool->getPropIDByEID(eID)));
        QList<int> nodeIDs = element->getAllNodes();
        for (QList<int>::iterator iter = nodeIDs.begin(); iter != nodeIDs.end(); ++iter)
            data.append(QString::number(*iter));
        //写出数据
        writeTool->writeData(data);
        return true;
    }

    bool FITKNastranAdaptorModelElement::writeCHEXA(Interface::FITKAbstractElement* element)
    {
        if (!element || !_writer) return false;
        //获取写出工具
        FITKNastranBDFIOWriterTool* writeTool = _writer->getWriterTool();
        if (!writeTool) return false;
        int eID = element->getEleID();
        //获取数据
        QStringList data;
        data.append("CHEXA");
        data.append(QString::number(eID));
        data.append(QString::number(writeTool->getPropIDByEID(eID)));
        QList<int> nodeIDs = element->getAllNodes();
        for (QList<int>::iterator iter = nodeIDs.begin(); iter != nodeIDs.end(); ++iter)
            data.append(QString::number(*iter));
        //写出数据
        writeTool->writeData(data);
        return true;
    }

    bool FITKNastranAdaptorModelElement::writeCTETRA(Interface::FITKAbstractElement* element)
    {
        if (!element || !_writer) return false;
        //获取写出工具
        FITKNastranBDFIOWriterTool* writeTool = _writer->getWriterTool();
        if (!writeTool) return false;
        int eID = element->getEleID();
        //获取数据
        QStringList data;
        data.append("CTETRA");
        data.append(QString::number(eID));
        data.append(QString::number(writeTool->getPropIDByEID(eID)));
        QList<int> nodeIDs = element->getAllNodes();
        for (QList<int>::iterator iter = nodeIDs.begin(); iter != nodeIDs.end(); ++iter)
            data.append(QString::number(*iter));
        //写出数据
        writeTool->writeData(data);
        return true;
    }
}
